package app

import (
	"context"
	"errors"
	"log"
	"time"

	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
	"gorm.io/gorm/schema"
	"jgame-api/config"
)

// createDB 创建gorm数据库连接池
func createDB(conf config.DBConfig) *gorm.DB {
	// gorm配置
	config := &gorm.Config{
		Logger: &gormLoggoer{log: logger.Default},
		// 使用单数表明
		NamingStrategy: schema.NamingStrategy{SingularTable: true},
	}

	db, err := gorm.Open(mysql.Open(conf.Dsn), config)
	if err != nil {
		log.Fatalf("database init fail: %v", err)
	}

	sqlDB, _ := db.DB()
	sqlDB.SetMaxOpenConns(conf.MaxOpenConn)
	sqlDB.SetMaxIdleConns(conf.MaxIdleConn)
	sqlDB.SetConnMaxIdleTime(time.Hour)
	sqlDB.SetConnMaxLifetime(2 * time.Hour)

	if err = sqlDB.Ping(); err != nil {
		log.Fatalf("database ping fail: %v", err)
	}
	return db
}

// closeDB 关闭grom数据库连接池
func closeDB(db *gorm.DB) {
	sqlDB, _ := db.DB()
	_ = sqlDB.Close()
}

type gormLoggoer struct {
	log logger.Interface
}

// LogMode log mode
func (g *gormLoggoer) LogMode(level logger.LogLevel) logger.Interface {
	return g.log.LogMode(level)
}

// Info print info
func (g gormLoggoer) Info(ctx context.Context, msg string, data ...interface{}) {
	g.log.Info(ctx, msg, data)
}

// Warn print warn messages
func (g gormLoggoer) Warn(ctx context.Context, msg string, data ...interface{}) {
	g.log.Warn(ctx, msg, data)
}

// Error print error messages
func (g gormLoggoer) Error(ctx context.Context, msg string, data ...interface{}) {
	g.log.Error(ctx, msg, data)
}

// Trace print sql message
func (g gormLoggoer) Trace(ctx context.Context, begin time.Time, fc func() (string, int64), err error) {
	if errors.Is(err, gorm.ErrRecordNotFound) {
		// 忽略record not found日志输出
		return
	}
	g.log.Trace(ctx, begin, fc, err)
}
